package cnm.storage.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.String;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Calendar;
import java.util.List;
import java.util.ArrayList;

import cnm.storage.StorageService;
import cnm.storage.UnsupportedStorageObject;
import cnm.model.*;

public class StorageServiceImpl implements StorageService {

	private String repoDir;
	private String tmpDir;
	
	public void init() {
		File repo = new File(getRepoDir());
		repo.mkdirs();
		File audio = new File(repo, "audio");
		audio.mkdirs();
		File video = new File(repo, "video");
		video.mkdirs();
		File magzine = new File(repo, "magzine");
		magzine.mkdirs();
		File image = new File(repo, "image");
		image.mkdirs();	
		File playlist = new File(repo, "playlist");
		playlist.mkdirs();			
	}
	
	public void setRepoDir(String repoDir) {
		this.repoDir = repoDir;
	}
	
	public String getRepoDir () {
		return this.repoDir;
	}
	
	public String getTmpDir() {
		return tmpDir;
	}

	public void setTmpDir(String tmpDir) {
		this.tmpDir = tmpDir;
	}

	public boolean loadStream(int type, String uuid, OutputStream outStream)
			throws UnsupportedStorageObject, IOException {
		String fileUri = getRepoDir();
		switch (type) {
			case ResourceTypes.TYPE_AUDIO:
				fileUri += File.separator + "audio"+ File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_VIDEO:
				fileUri += File.separator + "video" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_MAGZINE:
				fileUri += File.separator + "magzine" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_IMAGE:
				fileUri += File.separator + "image" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			default:
				throw new UnsupportedStorageObject(type, "Invalid type");
		}
		
		InputStream in = null;
		try {
			in = new BufferedInputStream(new FileInputStream(new File(fileUri)));
    		byte[] buffer = new byte[8*1024];
    		int length = -1;
    		while ((length=in.read(buffer))>-1) {
    			outStream.write(buffer, 0, length);
    		}	
    		outStream.flush();			
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (null != in) {
				in.close();
			}
		}
		return true;
	}

	public boolean saveStream(int type, String uuid, InputStream inStream)
			throws UnsupportedStorageObject, IOException {
		String fileUri = getRepoDir();
		switch (type) {
			case ResourceTypes.TYPE_AUDIO:
				fileUri += File.separator + "audio"+ File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_VIDEO:
				fileUri += File.separator + "video" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_MAGZINE:
				fileUri += File.separator + "magzine" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			case ResourceTypes.TYPE_IMAGE:
				fileUri += File.separator + "image" + File.separator + uuid + "." + ResourceTypesUtil.typeToExt(type);
				break;
			default:
				throw new UnsupportedStorageObject(type, "Invalid type");
		}
		
		BufferedInputStream in = null;
		BufferedOutputStream out = null;
		try {
			File file = new File(fileUri);	
    		in = new BufferedInputStream(inStream);
    		out = new BufferedOutputStream(new FileOutputStream(file));
    		byte[] buffer = new byte[8*1024];
    		int length = -1;
    		while ((length=in.read(buffer))>-1) {
    			out.write(buffer, 0, length);
    		}	
    		out.flush();
		}
		catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		finally {
			if (null!=out) {
				out.close();
			}		
		}
		
		return true;
	}

	public boolean persistTmpObject(int type, String tmpUuid, String persistUuid)
			throws UnsupportedStorageObject, IOException {
		// TODO Auto-generated method stub
		/*String tmpFileUri = getTmpDir() + File.separator + "audio" + 
			File.separator + tmpUuid + ".mp3";
		String persistFileUri = getRepoDir() + File.separator + "audio" + 
			File.separator + persistUuid + ".mp3";
		
		InputStream in = null;
		OutputStream out = null;		
		try {
			File tmpFile = new File(tmpFileUri);
			if (!tmpFile.exists()) {
				return false;
			} else {
				in = new BufferedInputStream(new FileInputStream(tmpFile));
				out = new BufferedOutputStream(new FileOutputStream(new File(persistFileUri)));
	    		byte[] buffer = new byte[8*1024];
	    		int length = -1;
	    		while ((length=in.read(buffer))>-1) {
	    			out.write(buffer, 0, length);
	    		}	
	    		out.flush();						
			}
		}
		catch(Exception e) {
			e.printStackTrace();
			return false;
		}
		finally {
			if (null!=in) {
				in.close();
			}
			if (null!=out) {
				out.close();
			}							
		}*/
		
		return true;
	}

	public boolean deleteResourceObject(int type, String uuid)
		throws UnsupportedStorageObject, IOException {
		String fileUri = getRepoDir();
		if (type == ResourceTypes.TYPE_AUDIO) {
			fileUri += File.separator + "audio" + File.separator + uuid + ".mp3";
		} else if (type == ResourceTypes.TYPE_IMAGE) {
			fileUri += File.separator + "image" + File.separator + uuid + ".jpg"; //FIXME: image type should be decided
		} else {
			throw new UnsupportedStorageObject(type, "Invalid type");
		}
		File file = new File(fileUri);
		if (file.exists()) {
			if (file.delete()) {
				return true;
			}
		} else {
			throw new UnsupportedStorageObject(type, "File not exists");
		}		
		return false;
	}
	
	public List<Program> loadPlayList(String listName) 
		throws IOException {
		String fileStr = getRepoDir() + File.separator + "playlist" + 
			File.separator + listName + ".txt";
		File file = new File(fileStr);
		if (file.exists()) {
			//TODO: read play list
			List<Program> list = new ArrayList<Program>(); 
			BufferedReader in = null;
			try {
    			in = new BufferedReader(new InputStreamReader(new FileInputStream(fileStr)));
    			String line = in.readLine();
    			while (line != null) {
    				Program program = new Program();
    				program.setProgramUuid(line);
    				list.add(program);
    				line = in.readLine();  				
    			}
    			return list;
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				in.close();
			}
		}	
		return null;
	}
	
	public boolean savePlayList(List<Program> playList, String listName)
		throws IOException {
		String fileStr = getRepoDir() + File.separator + "playlist" + 
			File.separator + listName + ".txt";		
		File file = new File(fileStr);
		if (!file.exists()) {
			//TODO: save play list
			BufferedWriter out = null;
			try {
    			out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileStr)));
				for (int i=0; i<playList.size(); i++) {
    				String line = playList.get(i).getProgramUuid() + "\r\n";
    				out.write(line);
    			}	
				return true;
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				out.close();
			}
		}		
		return false;
	}
	
}
